package com.example.limit.rule;

import com.example.limit.entity.PurchaseRule;
import com.example.limit.service.RedisCounterService;
import org.jeasy.rules.api.Facts;
import org.jeasy.rules.api.Rule;

import java.time.Duration;
import java.time.LocalDateTime;
import java.util.Map;

/**
 * 集成Redis计数服务的规则实现
 */
public class RedisAwareRule implements Rule {
    
    private final PurchaseRule dbRule;
    private final RedisCounterService counterService;
    
    public RedisAwareRule(PurchaseRule dbRule, RedisCounterService counterService) {
        this.dbRule = dbRule;
        this.counterService = counterService;
    }
    
    @Override
    public boolean evaluate(Facts facts) {
        Map<String, Object> context = facts.get("context");
        Long userId = (Long) context.get("userId");
        String productId = (String) context.get("productId");
        String categoryId = (String) context.get("categoryId");
        Integer quantity = (Integer) context.get("quantity");
        LocalDateTime purchaseTime = (LocalDateTime) context.get("purchaseTime");
        
        // 检查规则是否在有效期内
        if (!isRuleActive(purchaseTime)) {
            return false;
        }
        
        // 检查目标值匹配
        if (!matchesTarget(context)) {
            return false;
        }
        
        // 根据规则类型评估条件
        return evaluateWithRedis(userId, productId, categoryId, quantity, purchaseTime);
    }
    
    @Override
    public void execute(Facts facts) throws Exception {
        // 规则通过，记录结果
        Map<String, Object> results = facts.get("results");
        String ruleKey = "rule_" + dbRule.getId();
        results.put(ruleKey, true);
        results.put(ruleKey + "_name", dbRule.getRuleName());
        
        // 实际执行计数操作
        executeRedisCounting(facts);
    }
    
    private boolean isRuleActive(LocalDateTime purchaseTime) {
        return !purchaseTime.isBefore(dbRule.getStartTime()) && 
               !purchaseTime.isAfter(dbRule.getEndTime()) &&
               dbRule.getStatus() == 1;
    }
    
    private boolean matchesTarget(Map<String, Object> context) {
        if (dbRule.getTargetValue() == null || dbRule.getTargetValue().isEmpty()) {
            return true;
        }
        
        switch (dbRule.getRuleType()) {
            case 1: // 用户维度
                Long userId = (Long) context.get("userId");
                return dbRule.getTargetValue().equals(userId.toString());
            case 2: // 商品维度
                String productId = (String) context.get("productId");
                String categoryId = (String) context.get("categoryId");
                if (dbRule.getSubType() == 3) { // 单品
                    return dbRule.getTargetValue().equals(productId);
                } else if (dbRule.getSubType() == 4) { // 品类
                    return dbRule.getTargetValue().equals(categoryId);
                }
                break;
        }
        return true;
    }
    
    private boolean evaluateWithRedis(Long userId, String productId, String categoryId, 
                                    Integer quantity, LocalDateTime purchaseTime) {
        String redisKey = generateRedisKey(userId, productId, categoryId);
        Duration expireTime = Duration.between(purchaseTime, dbRule.getEndTime());
        
        // 检查是否超过限制
        return !counterService.isExceedLimit(redisKey, dbRule.getLimitQuantity(), quantity, expireTime);
    }
    
    private void executeRedisCounting(Facts facts) {
        Map<String, Object> context = facts.get("context");
        Long userId = (Long) context.get("userId");
        String productId = (String) context.get("productId");
        String categoryId = (String) context.get("categoryId");
        Integer quantity = (Integer) context.get("quantity");
        LocalDateTime purchaseTime = (LocalDateTime) context.get("purchaseTime");
        
        String redisKey = generateRedisKey(userId, productId, categoryId);
        Duration expireTime = Duration.between(purchaseTime, dbRule.getEndTime());
        
        // 实际增加计数
        counterService.increment(redisKey, quantity, expireTime);
    }
    
    private String generateRedisKey(Long userId, String productId, String categoryId) {
        switch (dbRule.getRuleType()) {
            case 1: // 用户维度
                if (dbRule.getSubType() == 1) { // 单用户限购
                    return counterService.generateKey("easyrule:user:limit", 
                        userId.toString(), productId, String.valueOf(dbRule.getId()));
                } else if (dbRule.getSubType() == 2) { // 新老用户
                    return counterService.generateKey("easyrule:user:type", 
                        userId.toString(), String.valueOf(dbRule.getId()));
                }
                break;
            case 2: // 商品维度
                if (dbRule.getSubType() == 3) { // 单品限购
                    return counterService.generateKey("easyrule:product:limit", 
                        productId, String.valueOf(dbRule.getId()));
                } else if (dbRule.getSubType() == 4) { // 品类限购
                    return counterService.generateKey("easyrule:category:limit", 
                        categoryId, String.valueOf(dbRule.getId()));
                }
                break;
            case 3: // 时间维度
                return counterService.generateKey("easyrule:time:limit", 
                    userId.toString(), productId, 
                    dbRule.getStartTime().toString(), dbRule.getEndTime().toString());
            case 4: // 订单维度
                if (dbRule.getSubType() == 7) { // 多订单累计
                    return counterService.generateKey("easyrule:order:accumulate", 
                        userId.toString(), productId, String.valueOf(dbRule.getId()));
                }
                break;
        }
        
        return counterService.generateKey("easyrule:default", String.valueOf(dbRule.getId()));
    }
    
    public PurchaseRule getDbRule() {
        return dbRule;
    }

    @Override
    public int compareTo(Rule o) {
        return 0;
    }
}